package com.insight.service;

import com.insight.dto.graph.GraphEdge;
import com.insight.dto.graph.GraphNode;
import com.insight.dto.graph.RelationshipGraph;
import com.insight.entity.MetadataTable;
import com.insight.entity.TableRelationship;
import com.insight.repository.MetadataTableRepository;
import com.insight.repository.TableRelationshipRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * T113: 表关系图生成服务
 * 实现图遍历和关系图生成逻辑
 *
 * @author Insight Team
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class RelationshipGraphService {

    private final TableRelationshipRepository relationshipRepository;
    private final MetadataTableRepository tableRepository;

    /**
     * 默认最大遍历深度(防止性能问题)
     */
    private static final int DEFAULT_MAX_DEPTH = 5;

    /**
     * 生成单个表的关系图
     * 包括该表的所有父表和子表
     *
     * @param tableId 表ID
     * @return 关系图
     */
    public RelationshipGraph generateGraphForTable(Long tableId) {
        return generateGraphForTable(tableId, DEFAULT_MAX_DEPTH);
    }

    /**
     * 生成单个表的关系图(指定最大深度)
     *
     * @param tableId  表ID
     * @param maxDepth 最大遍历深度
     * @return 关系图
     */
    public RelationshipGraph generateGraphForTable(Long tableId, Integer maxDepth) {
        log.info("生成表关系图: tableId={}, maxDepth={}", tableId, maxDepth);

        MetadataTable centerTable = tableRepository.findById(tableId)
                .orElseThrow(() -> new IllegalArgumentException("表不存在: " + tableId));

        // 使用Set防止循环引用
        Set<Long> visitedTableIds = new HashSet<>();
        Map<Long, GraphNode> nodeMap = new HashMap<>();
        List<GraphEdge> edges = new ArrayList<>();

        // 创建中心节点
        GraphNode centerNode = createNode(centerTable, "center", 0);
        nodeMap.put(tableId, centerNode);
        visitedTableIds.add(tableId);

        // 向上遍历父表(被引用的表)
        traverseAncestors(centerTable, nodeMap, edges, visitedTableIds, 1, maxDepth);

        // 向下遍历子表(引用中心表的表)
        traverseDescendants(centerTable, nodeMap, edges, visitedTableIds, 1, maxDepth);

        // 构建关系图
        return RelationshipGraph.builder()
                .centerNodeId(tableId)
                .dataSourceId(centerTable.getDataSource().getId())
                .maxDepth(maxDepth)
                .nodes(new ArrayList<>(nodeMap.values()))
                .edges(edges)
                .statistics(calculateStatistics(nodeMap, edges))
                .build();
    }

    /**
     * 生成数据源的完整关系图
     *
     * @param dataSourceId 数据源ID
     * @return 关系图
     */
    public RelationshipGraph generateGraphForDataSource(Long dataSourceId) {
        log.info("生成数据源关系图: dataSourceId={}", dataSourceId);

        List<TableRelationship> relationships = relationshipRepository.findByDataSourceId(dataSourceId);

        Map<Long, GraphNode> nodeMap = new HashMap<>();
        List<GraphEdge> edges = new ArrayList<>();

        // 遍历所有关系,构建节点和边
        for (TableRelationship rel : relationships) {
            MetadataTable sourceTable = rel.getSourceTable();
            MetadataTable targetTable = rel.getTargetTable();

            // 添加源表节点
            nodeMap.putIfAbsent(sourceTable.getId(), createNode(sourceTable, "child", null));

            // 添加目标表节点
            nodeMap.putIfAbsent(targetTable.getId(), createNode(targetTable, "parent", null));

            // 添加边
            edges.add(createEdge(rel));
        }

        return RelationshipGraph.builder()
                .dataSourceId(dataSourceId)
                .nodes(new ArrayList<>(nodeMap.values()))
                .edges(edges)
                .statistics(calculateStatistics(nodeMap, edges))
                .build();
    }

    /**
     * 向上遍历祖先表(递归)
     */
    private void traverseAncestors(MetadataTable currentTable,
                                   Map<Long, GraphNode> nodeMap,
                                   List<GraphEdge> edges,
                                   Set<Long> visitedTableIds,
                                   int currentDepth,
                                   int maxDepth) {
        if (currentDepth > maxDepth) {
            return;
        }

        // 查找当前表的所有父表关系
        List<TableRelationship> parentRelationships = relationshipRepository.findBySourceTable(currentTable);

        for (TableRelationship rel : parentRelationships) {
            MetadataTable parentTable = rel.getTargetTable();
            Long parentId = parentTable.getId();

            // 避免循环引用
            if (visitedTableIds.contains(parentId)) {
                continue;
            }

            // 添加父表节点
            GraphNode parentNode = createNode(parentTable, "parent", currentDepth);
            nodeMap.put(parentId, parentNode);
            visitedTableIds.add(parentId);

            // 添加边
            edges.add(createEdge(rel));

            // 递归遍历父表的父表
            traverseAncestors(parentTable, nodeMap, edges, visitedTableIds, currentDepth + 1, maxDepth);
        }
    }

    /**
     * 向下遍历后代表(递归)
     */
    private void traverseDescendants(MetadataTable currentTable,
                                     Map<Long, GraphNode> nodeMap,
                                     List<GraphEdge> edges,
                                     Set<Long> visitedTableIds,
                                     int currentDepth,
                                     int maxDepth) {
        if (currentDepth > maxDepth) {
            return;
        }

        // 查找当前表的所有子表关系
        List<TableRelationship> childRelationships = relationshipRepository.findByTargetTable(currentTable);

        for (TableRelationship rel : childRelationships) {
            MetadataTable childTable = rel.getSourceTable();
            Long childId = childTable.getId();

            // 避免循环引用
            if (visitedTableIds.contains(childId)) {
                continue;
            }

            // 添加子表节点
            GraphNode childNode = createNode(childTable, "child", currentDepth);
            nodeMap.put(childId, childNode);
            visitedTableIds.add(childId);

            // 添加边
            edges.add(createEdge(rel));

            // 递归遍历子表的子表
            traverseDescendants(childTable, nodeMap, edges, visitedTableIds, currentDepth + 1, maxDepth);
        }
    }

    /**
     * 创建图节点
     */
    private GraphNode createNode(MetadataTable table, String nodeType, Integer depth) {
        return GraphNode.builder()
                .tableId(table.getId())
                .tableName(table.getTableName())
                .tableComment(table.getTableComment())
                .tableSchema(table.getTableSchema())
                .nodeType(nodeType)
                .depth(depth)
                .build();
    }

    /**
     * 创建图边
     */
    private GraphEdge createEdge(TableRelationship rel) {
        return GraphEdge.builder()
                .sourceTableId(rel.getSourceTable().getId())
                .sourceTableName(rel.getSourceTable().getTableName())
                .targetTableId(rel.getTargetTable().getId())
                .targetTableName(rel.getTargetTable().getTableName())
                .constraintName(rel.getConstraintName())
                .sourceColumn(rel.getSourceColumn())
                .targetColumn(rel.getTargetColumn())
                .relationType(rel.getRelationType())
                .onDeleteRule(rel.getOnDeleteRule())
                .onUpdateRule(rel.getOnUpdateRule())
                .description(rel.getDescription())
                .build();
    }

    /**
     * 计算图统计信息
     */
    private RelationshipGraph.GraphStatistics calculateStatistics(Map<Long, GraphNode> nodeMap,
                                                                   List<GraphEdge> edges) {
        int totalTables = nodeMap.size();
        int totalRelationships = edges.size();

        // 统计孤立表(无入边无出边)
        Set<Long> connectedTables = new HashSet<>();
        for (GraphEdge edge : edges) {
            connectedTables.add(edge.getSourceTableId());
            connectedTables.add(edge.getTargetTableId());
        }
        int isolatedTables = totalTables - connectedTables.size();

        // 统计根表(只被引用,不引用其他表)
        Set<Long> sourceTables = new HashSet<>();
        Set<Long> targetTables = new HashSet<>();
        for (GraphEdge edge : edges) {
            sourceTables.add(edge.getSourceTableId());
            targetTables.add(edge.getTargetTableId());
        }

        Set<Long> rootTableIds = new HashSet<>(targetTables);
        rootTableIds.removeAll(sourceTables);
        int rootTables = rootTableIds.size();

        // 统计叶子表(只引用其他表,不被引用)
        Set<Long> leafTableIds = new HashSet<>(sourceTables);
        leafTableIds.removeAll(targetTables);
        int leafTables = leafTableIds.size();

        return RelationshipGraph.GraphStatistics.builder()
                .totalTables(totalTables)
                .totalRelationships(totalRelationships)
                .isolatedTables(isolatedTables)
                .rootTables(rootTables)
                .leafTables(leafTables)
                .build();
    }
}
